package com.aisino.encrypt;

import com.aisino.encrypt.algorithm.*;
import com.aisino.encrypt.entity.Digest;
import com.aisino.encrypt.entity.Symmetric;
import com.aisino.encrypt.exception.AisinoException;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

/**
 * 川航加密算法工具类
 *
 * @author 蒋帆
 * @datetime 2021-08-27
 * @description 川航加密算法工具类
 */
public class AisinoEncrypt {

    /**
     * 默认密钥
     */
    private static final String DEFAULT_KEY = "aisinodefkey";

    /**
     * 生成对称加密算法的密钥
     *
     * @param symmetric 算法类型
     * @return key 返回对称加密算法的密钥
     */
    public static String initSymmetricKey(Symmetric symmetric) {
        String key = null;
        try {
            //生成key
            KeyGenerator keyGenerator = KeyGenerator.getInstance(symmetric.getAlgorithm());
            //设置密钥长度
            keyGenerator.init(symmetric.getKeySize());
            //生成密钥对象
            SecretKey secretKey = keyGenerator.generateKey();
            //获取密钥
            byte[] keyBytes = secretKey.getEncoded();
            key = Base64.getEncoder().encodeToString(keyBytes);
        } catch (NoSuchAlgorithmException e) {
            throw new AisinoException(e);
        }
        return key;
    }


    /**
     * 根据传入的密钥位数生成密钥
     *
     * @param symmetric 加密类型（DES/DES3/AES）
     * @param keySize   密钥位数
     * @return 返回生成的密钥
     */
    public static String initKey(Symmetric symmetric, int keySize) {
        String key = null;
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(symmetric.getAlgorithm());
            keyGenerator.init(keySize);//初始化此密钥生成器,使其具有确定的密钥大小
            SecretKey secretKey = keyGenerator.generateKey();
            byte[] bs = secretKey.getEncoded();
            key = Base64.getEncoder().encodeToString(bs);
        } catch (NoSuchAlgorithmException e) {
            throw new AisinoException(e);
        }
        return key;
    }

    /**
     * 调用DH算法
     *
     * @return DH算法类
     */
    public static DH dhEncrypt() {
        return new DH();
    }

    /**
     * 调用RSA算法
     *
     * @return RSA算法类
     */
    public static RSA rsa() {
        return new RSA();
    }

    /**
     * 默认加密方法
     * 默认为RSA加密
     *
     * @param content 需要加密的内容
     * @return 返回加密后的内容
     */
    public static String encrypt(String content) {
        return SymmetricEncrypt.encrypt(content, DEFAULT_KEY, Symmetric.DES);
    }

    /**
     * 摘要算法加密
     * md5和SHA加密
     *
     * @param content 需要加密的内容
     * @param digest  摘要加密算法类型
     * @return MD5或SHA加密后的密文
     */
    public static String encryptDigest(String content, Digest digest) {
        return DigestEncrypt.encrypt(content, digest);
    }

    /**
     * 对称加密
     *
     * @param symmetric 加密类型
     * @param content   需要加密的内容
     * @param key       密匙
     * @return 返回加密后的密文
     */
    public static String encryptSymmetric(String content, String key, Symmetric symmetric) {
        return SymmetricEncrypt.encrypt(content, key, symmetric);
    }

    /**
     * 取得默认密钥值
     *
     * @return 默认密钥值
     */
    public static String getDefaultKey() {
        return DEFAULT_KEY;
    }

    /**
     * 默认解密方法
     * RSA解密
     *
     * @param ciphertext 密匙
     * @return 返回解密后的内容
     */
    public static String decrypt(String ciphertext) {
        return SymmetricEncrypt.decrypt(ciphertext, DEFAULT_KEY, Symmetric.DES);
    }

    /**
     * 对称解密
     *
     * @param ciphertext 密文
     * @param key        密钥
     * @param symmetric  对称加密类型
     * @return 返回解密后的内容
     */
    public static String decryptSymmetric(String ciphertext, String key, Symmetric symmetric) {
        return SymmetricEncrypt.decrypt(ciphertext, key, symmetric);
    }

    /**
     * 摘要加密前后比较
     *
     * @param context    加密内容
     * @param ciphertext 密匙
     * @param digest     加密类型
     * @return 返回比较结果
     */
    public static boolean matchDigest(String context, String ciphertext, Digest digest) {
        return DigestEncrypt.match(context, ciphertext, digest);
    }
    /**
     * 获取密钥的字节长度
     *
     * @param key 密钥
     * @return 密钥字节长度
     */
    public static int getKeyByteLength(String key) {
        return key.getBytes().length;
    }
}
